/******************************************************************************* * Copyright (c) 2007, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.corext.fix; import java.util.ArrayList; import org.eclipse.swt.widgets.Shell; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.TextEditGroup; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.ui.PlatformUI; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.NullChange; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.EnumConstantDeclaration; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.refactoring.CompilationUnitChange; import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jdt.ui.cleanup.ICleanUpFix; import org.eclipse.jdt.ui.text.java.IProblemLocation; import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages; import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; public class UnimplementedCodeFix extends CompilationUnitRewriteOperationsFix { public static final class MakeTypeAbstractOperation extends CompilationUnitRewriteOperation { private final TypeDeclaration fTypeDeclaration; public MakeTypeAbstractOperation(TypeDeclaration typeDeclaration) { fTypeDeclaration= typeDeclaration; } /** * {@inheritDoc} */ public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel linkedProposalPositions) throws CoreException { AST ast= cuRewrite.getAST(); ASTRewrite rewrite= cuRewrite.getASTRewrite(); Modifier newModifier= ast.newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD); TextEditGroup textEditGroup= createTextEditGroup(CorrectionMessages.UnimplementedCodeFix_TextEditGroup_label, cuRewrite); rewrite.getListRewrite(fTypeDeclaration, TypeDeclaration.MODIFIERS2_PROPERTY).insertLast(newModifier, textEditGroup); LinkedProposalPositionGroup group= new LinkedProposalPositionGroup("modifier"); //$NON-NLS-1$ group.addPosition(rewrite.track(newModifier), !linkedProposalPositions.hasLinkedPositions()); linkedProposalPositions.addPositionGroup(group); } } public static ICleanUpFix createCleanUp(CompilationUnit root, boolean addMissingMethod, boolean makeTypeAbstract, IProblemLocation[] problems) { Assert.isLegal(!addMissingMethod || !makeTypeAbstract); if (!addMissingMethod && !makeTypeAbstract) return null; if (problems.length == 0) return null; ArrayList operations= new ArrayList(); for (int i= 0; i < problems.length; i++) { IProblemLocation problem= problems[i]; if (addMissingMethod) { ASTNode typeNode= getSelectedTypeNode(root, problem); if (typeNode != null && !isTypeBindingNull(typeNode)) { operations.add(new AddUnimplementedMethodsOperation(typeNode)); } } else { ASTNode typeNode= getSelectedTypeNode(root, problem); if (typeNode instanceof TypeDeclaration) { operations.add(new MakeTypeAbstractOperation((TypeDeclaration) typeNode)); } } } if (operations.size() == 0) return null; String label; if (addMissingMethod) { label= CorrectionMessages.UnimplementedMethodsCorrectionProposal_description; } else { label= CorrectionMessages.UnimplementedCodeFix_MakeAbstractFix_label; } return new UnimplementedCodeFix(label, root, (CompilationUnitRewriteOperation[]) operations.toArray(new CompilationUnitRewriteOperation[operations.size()])); } public static IProposableFix createAddUnimplementedMethodsFix(final CompilationUnit root, IProblemLocation problem) { ASTNode typeNode= getSelectedTypeNode(root, problem); if (typeNode == null) return null; if (isTypeBindingNull(typeNode)) return null; AddUnimplementedMethodsOperation operation= new AddUnimplementedMethodsOperation(typeNode); if (operation.getMethodsToImplement().length > 0) { return new UnimplementedCodeFix(CorrectionMessages.UnimplementedMethodsCorrectionProposal_description, root, new CompilationUnitRewriteOperation[] { operation }); } else { return new IProposableFix() { public CompilationUnitChange createChange(IProgressMonitor progressMonitor) throws CoreException { CompilationUnitChange change= new CompilationUnitChange(CorrectionMessages.UnimplementedMethodsCorrectionProposal_description, (ICompilationUnit) root.getJavaElement()) { public Change perform(IProgressMonitor pm) throws CoreException { Shell shell= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); String dialogTitle= CorrectionMessages.UnimplementedMethodsCorrectionProposal_description; IStatus status= getStatus(); ErrorDialog.openError(shell, dialogTitle, CorrectionMessages.UnimplementedCodeFix_DependenciesErrorMessage, status); return new NullChange(); } }; change.setEdit(new MultiTextEdit()); return change; } public String getAdditionalProposalInfo() { return new String(); } public String getDisplayString() { return CorrectionMessages.UnimplementedMethodsCorrectionProposal_description; } public IStatus getStatus() { return new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, CorrectionMessages.UnimplementedCodeFix_DependenciesStatusMessage); } }; } } public static UnimplementedCodeFix createMakeTypeAbstractFix(CompilationUnit root, IProblemLocation problem) { ASTNode typeNode= getSelectedTypeNode(root, problem); if (!(typeNode instanceof TypeDeclaration)) return null; TypeDeclaration typeDeclaration= (TypeDeclaration) typeNode; MakeTypeAbstractOperation operation= new MakeTypeAbstractOperation(typeDeclaration); String label= Messages.format(CorrectionMessages.ModifierCorrectionSubProcessor_addabstract_description, BasicElementLabels.getJavaElementName(typeDeclaration.getName().getIdentifier())); return new UnimplementedCodeFix(label, root, new CompilationUnitRewriteOperation[] { operation }); } public static ASTNode getSelectedTypeNode(CompilationUnit root, IProblemLocation problem) { ASTNode selectedNode= problem.getCoveringNode(root); if (selectedNode == null) return null; if (selectedNode.getNodeType() == ASTNode.ANONYMOUS_CLASS_DECLARATION) { // bug 200016 selectedNode= selectedNode.getParent(); } if (selectedNode.getLocationInParent() == EnumConstantDeclaration.NAME_PROPERTY) { selectedNode= selectedNode.getParent(); } if (selectedNode.getNodeType() == ASTNode.SIMPLE_NAME && selectedNode.getParent() instanceof AbstractTypeDeclaration) { return selectedNode.getParent(); } else if (selectedNode.getNodeType() == ASTNode.CLASS_INSTANCE_CREATION) { return ((ClassInstanceCreation) selectedNode).getAnonymousClassDeclaration(); } else if (selectedNode.getNodeType() == ASTNode.ENUM_CONSTANT_DECLARATION) { EnumConstantDeclaration enumConst= (EnumConstantDeclaration) selectedNode; if (enumConst.getAnonymousClassDeclaration() != null) return enumConst.getAnonymousClassDeclaration(); return enumConst; } else { return null; } } private static boolean isTypeBindingNull(ASTNode typeNode) { if (typeNode instanceof AbstractTypeDeclaration) { AbstractTypeDeclaration abstractTypeDeclaration= (AbstractTypeDeclaration) typeNode; if (abstractTypeDeclaration.resolveBinding() == null) return true; return false; } else if (typeNode instanceof AnonymousClassDeclaration) { AnonymousClassDeclaration anonymousClassDeclaration= (AnonymousClassDeclaration) typeNode; if (anonymousClassDeclaration.resolveBinding() == null) return true; return false; } else if (typeNode instanceof EnumConstantDeclaration) { return false; } else { return true; } } public UnimplementedCodeFix(String name, CompilationUnit compilationUnit, CompilationUnitRewriteOperation[] fixRewriteOperations) { super(name, compilationUnit, fixRewriteOperations); } }